﻿#ifndef PLAYBACKCONTROL_H
#define PLAYBACKCONTROL_H

#include <QDate>
#include <QPair>
#include <QMutex>
#include <QQueue>
#include <QObject>
#include <QVariant>
#include <QListIterator>
#include "GY_QtTimer.h"
#include "GY_CPUCounterTimer.h"
#include "GY_ControlLibrary_global.h"

class GY_CONTROLLIBRARY_EXPORT PlayBackControl : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief The PlayBackDataInfo struct 回放数据信息
     */
    struct PlayBackDataInfo{
        //!日期
        QDate date;
        //!时间
        quint64 time;
        //!消息id
        QVariant msgId;
        //!数据
        QVariant data;
        //!初始数据
        PlayBackDataInfo(){
            date=QDate(2000,1,1);
        }
    };
    /**
     * @brief The PlayBackTimerType enum 回放计时器类型
     */
    enum PlayBackTimerType{
        //!CPU计数器计时
        CPUTimer,
        //!QT定时器计时
        QtTimer
    };

    /**
     * @brief The PlayMode enum 播放模式
     */
    enum PlayMode{
        //!快进
        Forward = 1,
        //!快退
        BackOff = -1,
    };

    /**
     * @brief PlayBackControl 回放控制
     * @param mode 计时器类型
     * @param parent
     */
    explicit PlayBackControl(const PlayBackTimerType mode = QtTimer, QObject *parent = nullptr);
    ~PlayBackControl();

    /**
     * @brief setTimerMode 设置计时器类型
     * @param mode 类型
     */
    void setTimerMode(const PlayBackTimerType mode);
    /**
     * @brief setCurrentDateTime 设置当前日期、时间
     * @param time 时间
     * @param date 日期
     */
    void setCurrentDateTime(const quint64 &time,const QDate &date = QDate(2000,1,1));
    /**
     * @brief currentDateTime 获取当前日期事件
     * @return  返回当前日期时间
     */
    QDateTime currentDateTime() const;
    /**
     * @brief currentDate 获取当前日期
     * @return 当前日期
     */
    QDate currentDate() const;
    /**
     * @brief currentTime 获取当前时间
     * @return 当前时间(微妙数)
     */
    quint64 currentTime() const;
    /**
     * @brief setPlayMode 设置播放模式
     * @param mode 待设置的模式
     */
    void setPlayMode(PlayBackControl::PlayMode mode);
    /**
     * @brief playMode 获取播放模式
     * @return 播放模式枚举(前进/后退)
     */
    PlayBackControl::PlayMode playMode() const;
    /**
     * @brief setPlaySpeed 设置播放倍速
     * @param speed 待设置的倍速
     */
    void setPlaySpeed(double speed);
    /**
     * @brief playSpeed 获取播放速度
     * @return 播放倍速
     */
    double playSpeed() const;
    /**
     * @brief clear 清除回放数据
     */
    void clear();
    /**
     * @brief startPlayBack
     * 开始回放
     */
    void startPlayBack();
    /**
     * @brief stopPlaying
     * 停止播放
     */
    void stopPlaying();
    /**
     * @brief pausePlaying
     * 暂停播放
     */
    void pausePlaying();
    /**
     * @brief startDate 开始日期
     * @return 返回开始日期
     */
    QDate startDate() const;
    /**
     * @brief endDate 结束日期
     * @return 返回结束日期
     */
    QDate endDate() const;
    /**
     * @brief startTime 开始时间
     * @return 返回开始时间
     */
    qint64 startTime() const;
    /**
     * @brief endTime 结束时间
     * @return  返回结束时间
     */
    qint64 endTime() const;
private:
    /**
    * @brief findPlayBackDatas 根据当前快进或快退模式查早当前时间前或后所有数据包
    * @param time 当前时间
    * @param date 当前日期
    * @return 数据包迭代器
    **/
    QPair<QList<PlayBackDataInfo>::iterator, QList<PlayBackDataInfo>::iterator> findPlayBackDatas(qint64 time, const QDate& date);

public slots:
    /**
     * @brief addPlayBackData 添加回放数据
     * @param date 日期
     * @param time 时间：us
     * @param msgId 消息id
     * @param data 数据
     */
    void addPlayBackData(const QDate& date, const quint64 &time, const QVariant &msgId, const QVariant &data);
    /**
     * @brief timeOutEvent 定时器事件
     * @param currentDate 日期
     * @param currentTime 时间
     */
    void timeOutEvent(const QDate &currentDate,const qint64 &currentTime);
    /**
     * @brief setStartEndDateTime 设置开始、结束的日期和时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param startDate 开始日期：默认2000-1-1
     * @param endDate 结束日期：默认2000-1-1
     */
    void setStartEndDateTime(const quint64 &startTime, const quint64 &endTime, const QDate &startDate = QDate(2000,1,1), const QDate &endDate = QDate(2000,1,1));

signals:
    /**
     * @brief sendPlayBackDataSignal 发送回放数据信号
     * @param msgId 消息id
     * @param data 数据
     */
    void sendPlayBackDataSignal(const QDate& date, const quint64& time, const QDate& dataDate = QDate(2000,1,1), const quint64& dataTime = 0, const QVariant &msgId = QVariant(), const QVariant& data = QVariant());
    /**
     * @brief addForwardDataQueSignal 通知添加快进数据到队列的信号
     */
    void addForwardDataQueSignal();
    /**
     * @brief addBackOffDataQueSignal 通知添加快退数据到队列的信号
     */
    void addBackOffDataQueSignal();
private:

    //!回放数据队列
    QQueue<PlayBackDataInfo> m_PlayBackDatas;
    //!回放计时器类型
    PlayBackTimerType m_TimerType;
    //!开始时间
    quint64 m_StartTime;
    //!开始日期
    QDate m_StartDate;
    //!结束时间
    quint64 m_EndTime;
    //!结束日期
    QDate m_EndDate;
    //!qt计时器
    GY_QtTimer* m_pQtTimer;
    //!cpu计数器
    GY_CPUCounterTimer* m_pCPUTimer;
    //!运行标志
    bool isRuning;
    //!播放速度
    double m_PlaySpeed;
    //!播放模式
    PlayMode m_PlayMode;
    //!线程互斥锁
    QMutex m_Mutex;
};

#endif // PLAYBACKCONTROL_H
